require( "gip")
require( "util")
require( "imageswf")

local pakTarget
local basePath
local genPath
local directionNum
local baseX
local baseY
local failedCount
local successCount
local descFailedCount
local actionPlayVs = {}
local actionImageNum = {}
local addMode = false

local firstBodyName = "body"       -- 第一个body的名字, 主角从body01开始

local function getActionPlayV( actName)
    local v = actionPlayVs[actName] or actionPlayVs["_default"] 
    return v or 6
end

local srcImageSuffix1 = ".png"
local srcImageSuffix2 = ".tga"

local actionImages = {}
local actionImagesKeys = {}



local function imageFileCallBack( filename, isFile)
    filename = string.lower(filename)
    local dotPos = string.find( filename, srcImageSuffix1, #filename - 4)
    if dotPos == nil then
        dotPos = string.find( filename, srcImageSuffix2, #filename - 4)
    end
    if dotPos == nil then
        return
    end
   
    -- 根据方向整理一下名字
    local relPath = string.sub( filename, #basePath + 1, #filename - 4)
    if directionNum == 5 then
        local p, f = splitPath( filename)
        local c = string.sub( f, 1, 1)
        if c == "5" or c == "6" or c == "7" then
            return -- 5/6/7方向丢掉相应的图片
        end
    elseif directionNum == 1 then
        if string.find( relPath, "0") == 1 then
            relPath = "4" .. string.sub( relPath, 1, #relPath - 1)
        end
    elseif directionNum == 3 then
        if string.find( relPath, "0") == 1 then
            relPath = "3" .. string.sub( relPath, 1, #relPath - 1)
        elseif string.find( relPath, "1") == 1 then
            relPath = "4" .. string.sub( relPath, 1, #relPath - 1)
        elseif string.find( relPath, "2") == 1 then
            relPath = "5" .. string.sub( relPath, 1, #relPath - 1)
        end
    elseif directionNum == 4 then
        if string.find( relPath, "0") == 1 then
            relPath = "1" .. string.sub( relPath, 1, #relPath - 1)
        elseif string.find( relPath, "1") == 1 then
            relPath = "3" .. string.sub( relPath, 1, #relPath - 1)
        elseif string.find( relPath, "2") == 1 then
            relPath = "5" .. string.sub( relPath, 1, #relPath - 1)
        elseif string.find( relPath, "3") == 1 then
            relPath = "7" .. string.sub( relPath, 1, #relPath - 1)
        end
    end
    
    local image = gip.load( filename)
    if image == nil then
        print( "\n")
        print( filename .. "load failed!")
        failedCount = failedCount + 1
        return
    end
    
    local x, y, w, h = image.validArea()
    io.write( ".")
    local newImage = image.cut( x, y, w, h)
    image = nil
    
    local newPath = relPath .. ".jai"
    successCount = successCount + 1

    local v = {}
    v.image = newImage
    v.offsetX = x - baseX;
    v.offsetY = y - baseY;
    v.w = w;
    v.h = h;
    
    local key = noSuffixFileName( newPath)
    if #key == 3 then
        key = "4" .. key
    end
    actionImages[key] = v
    table.insert(actionImagesKeys, key)
end

local function calcActionImageNum()
    if #actionImagesKeys == 0 then
        return 0
    end

    local c1 = string.sub( actionImagesKeys[1], 1, 1)
    local num = 1
    local i
    for i = 2, #actionImagesKeys do
        if string.sub( actionImagesKeys[i], 1, 1 ) == c1 then
            num = num + 1
        else
            return num
        end
    end
    return num
end

local function outputJai( actionImages, actionImageKeys, newPath)
    newPath = newPath .. ".jai"
    
    gip.createParentDir( newPath)
    local jaiFile, errMsg = io.open( newPath, "wb")
    if jaiFile == nil then
        print( "open " .. newPath .. " failed: " .. errMsg)
        failedCount = failedCount + 1
        return
    end

    local imageCount = table.getn( actionImagesKeys)

    local headerSize = 0

    jaiFile:write( "jai")
    jaiFile:write( numbertobytes(0, 1))
    headerSize = headerSize + 4 

    jaiFile:write( numbertobytes(1, 2))
    headerSize = headerSize + 2 

    jaiFile:write( numbertobytes(imageCount, 2))
    headerSize = headerSize + 2 
    
    local ok = true
    for _, k in ipairs(actionImagesKeys) do
        local v = actionImages[k]
        headerSize = headerSize + #k
        -- k_len, w, h, ox, oy, offset[4], flag
        headerSize = headerSize + 2 * 6 + 4
        if v.image == nil then
            v.buf = numbertobytes( 0, 4)  -- for empty image
        else
            if addMode then
                v.flag = 1
                v.buf = v.image.saveToMemory( "jpg")
            else
                v.flag = 2
                v.buf = v.image.saveToMemory( "jai")
            end
            if v.buf == nil then
                ok = false
                failedCount = failedCount + 1
                print( filename .. "/" .. k .. " failed") 
                return;
            end
        end
    end
   
    local offset = headerSize
    for _, k in ipairs(actionImagesKeys) do
        local v = actionImages[k]
        v.offset = offset
        offset = offset + string.len( v.buf)
        if addMode then
            offset = offset + 4     -- for jpeg len
        end
    end

    for _, k in ipairs(actionImagesKeys) do
        local v = actionImages[k]
        jaiFile:write( numbertobytes(#k, 2))
        jaiFile:write( k)
        jaiFile:write( numbertobytes(v.w, 2))
        jaiFile:write( numbertobytes(v.h, 2))
        jaiFile:write( numbertobytes(v.offsetX, 2))
        jaiFile:write( numbertobytes(v.offsetY,2))
        jaiFile:write( numbertobytes(v.offset, 4))
        jaiFile:write( numbertobytes(v.flag, 2))
    end

    for _, k in ipairs(actionImagesKeys) do
        local v = actionImages[k]
        if addMode then
            jaiFile:write( numbertobytes(string.len(v.buf), 4))
        end
        jaiFile:write( v.buf)
    end

    jaiFile:flush()
    jaiFile:close()
end

local function outputSwf( actionImages, actionImagesKeys, actName, newPath, cmpQuality)
    newPath = newPath .. ".swf"
    gip.createParentDir( newPath)

    local srcFile = genSwf( actionImages, actionImagesKeys, actName, cmpQuality)
    local cmd = "cp " .. srcFile .. " " .. newPath
    os.execute( cmd)
    print( cmd)
end

local function actionCallback( filename, isFile)
    if ifFile then
        return
    end
    actionImages = {}
    actionImagesKeys = {}

    local parentPath, actName = splitPath( filename)
    
    local cmpQuality = 60
    if actName == "stand1" then
        cmpQuality = 90
    end
    gip.setJpgQuality( cmpQuality)

    gip.transDir( filename, imageFileCallBack, false)
    
    local imageCount = table.getn( actionImagesKeys) 
    if imageCount < 1 then
        return
    end
    
    table.sort( actionImagesKeys)

    if string.find( parentPath, firstBodyName, -(#firstBodyName+1)) ~= nil then
        actionImageNum[actName] = calcActionImageNum()
    end

    local relPath = string.sub( filename, #basePath + 1, #filename)
    local newPath = genPath .. relPath

    --outputJai( actionImages, actionImagesKeys, newPath)
    outputSwf( actionImages, actionImagesKeys, actName, newPath, cmpQuality)
    
end

local numForTest = 0
local totalForTest = 1

local function spriteCallback( filename, isFile)
    if isFile then
        return
    end

    --[[    
    if numForTest >= totalForTest then
        return
    end
    numForTest = numForTest + 1
    ]]

    local _, sDir = splitPath( filename)
    if pakTarget == "deft" then
        if string.find( sDir, "a") == 1 then
            addMode = true
        else
            addMode = false
        end
    end
   
    local partList = {}
    --local partList = ""
    local first = true
    actionImageNum = {}
    function _partCallback( filename, isFile)
        if not isFile then
            local _, partDir = splitPath( filename)
            table.insert( partList, partDir)
            --[[if first then
                partList = partDir
                first = false
            else
                partList = partList .. " " .. partDir
            end]]
            gip.transDir( filename, actionCallback, false)
        end
    end
    gip.transDir( filename, _partCallback, false)
    table.sort( partList)
    
    local actList = ""
    first = true
    -- write action description
    function _actCallback( filename, isFile)
        if not isFile then
            -- get action directory
            local _, actDir = splitPath( filename)
            --table.insert( actList, actDir)
            local imageNum = actionImageNum[actDir]
            if imageNum == nil then
                imageNum = 0
            end
            if first then
                actList = actDir .. "%" .. tostring( imageNum) ..
                    "%" .. tostring(getActionPlayV( actDir))
                first = false
            else
                actList = actList .. " " .. actDir .. "%" .. 
                    tostring( imageNum) .. "%" ..
                    tostring(getActionPlayV( actDir))
            end
        end
    end
    local bodyPath = filename .. "/" .. firstBodyName
    gip.transDir( bodyPath, _actCallback, false);
    
    local _, lastDir = splitPath( filename)
    local descFileName = string.format( "%s/%s/desc.txt", genPath, lastDir)
    local descFile = io.open( descFileName, "w")
    if descFile ~= nil then
        local s = string.format( "direction %d\r\n", directionNum)
        descFile:write( s)
        if #partList > 0 then
            descFile:write( "parts ")
            for k, v in ipairs(partList) do
                descFile:write( v)
                descFile:write( " ")
            end
            --descFile:write( partList)
            descFile:write( "\r\n")
            descFile:write( "actions ")
            descFile:write( actList)
        end
        descFile:close()
    end
end

local function genPakSprite( srcPath, dstPath, drtNum, bx, by)
    basePath = srcPath
    genPath = dstPath
    directionNum = drtNum or 8
    baseX = bx or 256
    baseY = by or 282
    failedCount = 0
    successCount = 0
    descFailedCount = 0
    
    --gip.setJpgQuality( 90)
    gip.transDir( basePath, spriteCallback, false)
    
    if failedCount == 0 and descFailedCount == 0 then
        print( "It's all OK!")
    else
        local s = string.format( "success: %d, failed: %d, desc fialed: %d",
            successCount, failedCount, descFailedCount)
        print( s)
    end
end

return function( target)
    gip.init()

    pakTarget = target

    if target == "monster" then
        actionPlayVs = {
            ["stand1"] = 5,
        }
        actionPlayVs["_default"] = 6
        firstBodyName = "body"
        gip.setJpgQuality( 75)
        addMode = false
        genPakSprite( "/export/arts/pak/monster_png",
            "/export/arts/pak/monster_pak", 5)
        --genPakSprite( "/home/wzp/dtools/gip/tools",
        --    "./monster_pak", 5)
    elseif target == "npc" then
        actionPlayVs = {}
        actionPlayVs["_default"] = 4
        actionPlayVs["stand1"] = 2
        firstBodyName = "body"
        gip.setJpgQuality( 75)
        addMode = false
        genPakSprite( "/export/arts/pak/npc_png",
            "/export/arts/pak/npc_pak", 1)
    elseif target == "charecter" then
        actionPlayVs = {}
        actionPlayVs["_default"] = 8 
        firstBodyName = "body00"
        gip.setJpgQuality( 75)
        addMode = false
        genPakSprite( "/export/arts/pak/charecter_tga",
            "/export/arts/pak/charecter_pak", 5)
        --genPakSprite( "/home/wzp/dtools/gip/tools",
        --    "./monster_pak", 5)
    elseif target == "deft" then     --带方向的特效
        actionPlayVs = {
            ["stand1"] = 5,
        }
        actionPlayVs["_default"] = 6
        firstBodyName = "body"
        gip.setJpgQuality( 50)
        addMode = false 
        genPakSprite( "/export/arts/pak/deft_png",
            "/export/arts/pak/deft_pak", 5)
    else
        print( "invalid target")
    end

    gip.deInit()
end
